Skip to content

Conversation

@hannesrudolph
Copy link
Collaborator

@hannesrudolph hannesrudolph commented Feb 6, 2026

Closes #11246

After
image

Summary

Consolidates consecutive list_files, read_file, and file-edit tool ask messages into single grouped UI blocks in the chat — reducing visual clutter when the agent performs multiple similar operations in sequence.

Before: Multiple consecutive list_files calls each render their own "Roo wants to view the top level files in this directory" block with repeated headers. Same for consecutive file edits.

After: They collapse into a single block with all paths listed together.

Changes

New files

  • webview-ui/src/utils/batchConsecutive.ts — Generic utility that walks a message array and batches consecutive matches into synthetic messages. Used for all three batching passes (read_file, list_files, file-edits).
  • webview-ui/src/utils/__tests__/batchConsecutive.spec.ts — 11 test cases covering empty input, passthrough, batching, mixed sequences, generic typing, immutability, and edge cases.

Modified files

  • packages/types/src/vscode-extension-host.ts — Added batchDirs property to ClineSayTool interface
  • webview-ui/src/components/chat/ChatView.tsx — Replaced three near-identical batching while-loops (~170 lines) with three batchConsecutive() calls (~70 lines). Added batch button text for listFilesTopLevel/listFilesRecursive and edit-file batches ("Save All"/"Deny All"). Added JSON.parse defense-in-depth in all three synthesizers.
  • webview-ui/src/components/chat/ChatRow.tsx — Merged listFilesTopLevel/listFilesRecursive cases; added batch detection for BatchListFilesPermission; normalized language prop to "shellsession"; moved batchDiffs check before switch for all file-edit tool types. Fixed mixed list_files batch icon to default to FolderTree.
  • webview-ui/src/components/chat/BatchListFilesPermission.tsx — New component for grouped directory listing UI. Fixed React key to include array index.
  • webview-ui/src/components/chat/BatchFilePermission.tsx — Fixed React key to include array index.
  • webview-ui/src/components/chat/BatchDiffApproval.tsx — Fixed React key to include array index.
  • webview-ui/src/components/chat/__tests__/BatchListFilesPermission.spec.tsx — 5 tests covering rendering, empty state, re-render, container structure, and batch icon fallback.
  • webview-ui/src/i18n/locales/en/chat.json — Added wantsToViewMultipleDirectories, dedicated list-batch/edit-batch i18n keys (stop reusing read-batch keys).
  • 17 other locale chat.json files — Added wantsToViewMultipleDirectories; removed unused didViewMultipleDirectories

Audit improvements

The following quality fixes were applied during code review:

  • Generic batchConsecutive() — Refactored from ClineMessage-specific to a fully generic <T> utility, improving reusability and type safety.
  • Edit-batch button text — Added batch-aware "Save All" / "Deny All" button labels for file-edit batches (previously missing).
  • Dedicated i18n keys — Added list-batch.* and edit-batch.* i18n key namespaces instead of reusing read-batch keys for different tool types.
  • JSON.parse defense-in-depth — Wrapped all three batch synthesizers with try/catch around JSON.parse calls to prevent runtime crashes on malformed message content.
  • Mixed list_files batch icon — Fixed icon for batches mixing listFilesTopLevel and listFilesRecursive to default to FolderTree instead of rendering incorrectly.
  • +6 new test cases — Added tests for all-match batching, immutability guarantees, spy-based verification, single-directory edge case, and batch icon fallback.

Footnote — Minor out-of-scope cleanup:
These changes are unrelated to the batch tool-call feature but were discovered during code review and cleaned up while in the area:

  • Trimmed unused recursive/isOutsideWorkspace fields from DirPermissionItem interface in BatchListFilesPermission.tsx (the upstream type in vscode-extension-host.ts retains them)
  • Removed 4 pre-existing as any casts in ChatView.tsx — replaced with proper types (ClineMessage, inline window type, direct bracket access, correct debounce API)

Design rationale — which tools are batched and why

This PR batches only homogeneous, low-context tool calls where the meaningful information is a file/directory path:

Tool type Batched? Reason
list_files ✅ Yes Output is a directory path — multiple listings collapse naturally into a path list
read_file ✅ Yes Output is a file path — multiple reads collapse into a file list with per-file approval
File edits (editedExistingFile, appliedDiff, newFileCreated, insertContent, searchAndReplace) ✅ Yes Output is a diff — multiple edits collapse into expandable per-file diffs
codebaseSearch ❌ No Each search has a unique query returning 20–30 ranked results with scores and code snippets. Batching would lose the query→result mapping.
searchFiles ❌ No Each regex search returns different result counts and patterns. Per-query context is essential.
execute_command ❌ No Commands have different risk profiles. Users must see and approve each one individually (security concern).

Guiding principle: Batch when the per-call output is a simple path or diff. Don't batch when each result has rich, query-specific content that would be lost in a combined view.

Consolidate consecutive listFilesTopLevel/listFilesRecursive ask messages
into a single 'Roo wants to view multiple directories' block, matching the
existing read_file batching pattern.
@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. UI/UX UI/UX related or focused labels Feb 6, 2026
@roomote
Copy link
Contributor

roomote bot commented Feb 6, 2026

Oroocle Clock   See task

The latest commit (c15377e) adds list-batch and edit-batch i18n translations across all 17 non-English locale files. Structure is consistent with the English source and all locales properly differentiate "Approve All" vs "Save All" labels. No new issues found.

  • Consolidate the duplicate batch-handling blocks in ChatRow.tsx for listFilesTopLevel and listFilesRecursive into a single combined case
Previous reviews

Mention @roomote in a comment to request specific changes to this pull request or fix all unresolved issues.

@hannesrudolph hannesrudolph force-pushed the feat/batch-list-files-ui branch from db94d81 to 0160847 Compare February 6, 2026 05:21
…atRow

Merge the separate listFilesTopLevel and listFilesRecursive case blocks
into a single combined case with shared batch-detection logic, selecting
the icon and translation key based on the tool type. This removes the
duplicated isBatchDirRequest check and BatchListFilesPermission render.
Add edit-file batching in ChatView groupedMessages that consolidates
consecutive editedExistingFile, appliedDiff, newFileCreated,
insertContent, and searchAndReplace asks into a single BatchDiffApproval
block. Move batchDiffs detection in ChatRow above the switch statement
so it applies to any file-edit tool type.
- Extract generic batchConsecutive() utility from 3 identical while-loops
- Fix React key collisions in BatchListFilesPermission, BatchFilePermission, BatchDiffApproval
- Normalize language prop to "shellsession" (was "shell-session" for top-level)
- Remove unused _batchedMessages property from synthetic messages
- Remove dead didViewMultipleDirectories i18n key from all 18 locale files
- Add batch button text for listFilesTopLevel/listFilesRecursive
- Add batchConsecutive utility tests (6 cases)
@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Feb 6, 2026
@hannesrudolph hannesrudolph changed the title feat: group consecutive list_files tool calls into single UI block feat: batch consecutive tool calls in chat UI with shared utility Feb 6, 2026
- Make batchConsecutive() generic instead of ClineMessage-specific
- Add batch-aware button text for edit-file batches ("Save All"/"Deny All")
- Add dedicated list-batch/edit-batch i18n keys (stop reusing read-batch)
- Add JSON.parse defense-in-depth in all three synthesizers
- Fix mixed list_files batch icon to default to FolderTree
- Add 6 missing test cases (all-match, immutability, spy, single-dir)
- Trim unused recursive/isOutsideWorkspace from DirPermissionItem interface
- Remove 4 pre-existing `as any` casts in ChatView.tsx:
  - window cast → precise inline type
  - checkpoint bracket access → removed unnecessary casts
  - condensing message → `as ClineMessage`
  - debounce cancel → `.clear()` (correct API)
- Update BatchListFilesPermission test data to match trimmed interface
@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Feb 9, 2026
@daniel-lxs daniel-lxs merged commit 7afa436 into main Feb 9, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm This PR has been approved by a maintainer size:XL This PR changes 500-999 lines, ignoring generated files. UI/UX UI/UX related or focused

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parallel list_files tool calls render as repetitive separate blocks

2 participants